package sporteam.web.client;

import java.io.Serializable;
import java.util.Date;

import javax.jdo.annotations.EmbeddedOnly;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

@SuppressWarnings("serial")
@PersistenceCapable(embeddedOnly = "true")
@EmbeddedOnly
public class Competition implements Serializable {
	/**
	 * Two main kinds of competitions: - by time - by goal these describe how to
	 * competiton will end.
	 * 
	 * each kind can be of type - CALORIES, DISTANCE, TIME
	 */

	// Will hold runners ids
	@Persistent
	private String runner1Id;
	@Persistent
	private String runner2Id;

	// Will hold runners scores
	@Persistent
	private double runner1Score;
	@Persistent
	private double runner2Score;

	@Persistent
	private Date creationtime;
	@Persistent
	private Date endTime;

	// Will hold the numeric goal if the competiton is by time
	@Persistent
	private int goal;

	@Persistent
	private CompetitionType type;

	@Persistent
	private boolean closed = false;

	public Competition() {
		// TODO Auto-generated constructor stub
	}
	
	public Competition(String runner1Id, String runner2Id, CompetitionType type) {
		this.setRunner1Id(runner1Id);
		this.setRunner2Id(runner2Id);
		this.setRunner1Score(0);
		this.setRunner2Score(0);
		this.setCreationtime(new Date());
		this.setEndTime(null);
		this.closed = false;
	}

	public String getRunner1Id() {
		return runner1Id;
	}

	public void setRunner1Id(String runner1Id) {
		this.runner1Id = runner1Id;
	}

	public String getRunner2Id() {
		return runner2Id;
	}

	public void setRunner2Id(String runner2Id) {
		this.runner2Id = runner2Id;
	}

	public double getRunner1Score() {
		return runner1Score;
	}

	public void setRunner1Score(double runner1Score) {
		this.runner1Score = runner1Score;
	}

	public double getRunner2Score() {
		return runner2Score;
	}

	public void setRunner2Score(double runner2Score) {
		this.runner2Score = runner2Score;
	}

	public Date getCreationtime() {
		return creationtime;
	}

	public void setCreationtime(Date creationtime) {
		this.creationtime = creationtime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public CompetitionType getType() {
		return type;
	}

	public void setType(CompetitionType type) {
		this.type = type;
	}
	/*returns true iff id given equals runner1Id or runner2Ids*/
	public boolean inCompetiton(String id) {
		return (id.equals(runner1Id) || id.equals(runner2Id));
	}

	public int getGoal() {
		return goal;
	}

	public void setGoal(int goal) {
		this.goal = goal;
	}

	public boolean isClosed() {
		return closed;
	}

	public void setClosed(boolean closed) {
		this.closed = closed;
	}
	public void closeCompetition(){
		this.closed = true;
	}

	
	public void updateScoreByTrack(Track track, String id){
		if(id.equals(runner1Id)){
			runner1Score += getScoreFromTrack(track);
		}
		else if(id.equals(runner2Id)){
			runner2Score += getScoreFromTrack(track);
		}
	}
	
	
	/* Will calculate the score atm (can be called only from the sever-side) */
	public void calculateScore(AEuser user1, AEuser user2) {
		this.runner1Score = calculateScoreForUser(user1);
		this.runner2Score = calculateScoreForUser(user2);

	}

	private double calculateScoreForUser(AEuser user) {
		double trackScore = 0;
		double totalScore = 0;
		for (Track track : user.GetTracks()) {
			if (isValidTrack(track)) {	// Consider only tracks with date later than creationTime
				trackScore = getScoreFromTrack(track);
				totalScore += trackScore;
			}
		}
		return totalScore;
	}

	private boolean isValidTrack(Track track) {
		Date trackDate = new Date(track.date);
		if(creationtime.before(trackDate)){
			return true;
		}
		return false;
	}

	private double getScoreFromTrack(Track track) {
		if (this.type.equals(CompetitionType.CALORIES)) {
			return track.calories;
		} else if (this.type.equals(CompetitionType.DISTANCE)) {
			return track.distance;
		} else if (this.type.equals(CompetitionType.TIME)) {
			return track.time;
		}
		return 0;
	}
	
	public String getOtherId(String id){
		if(id.equals(runner1Id)){
			return runner2Id;
		}
		else if(id.equals(runner2Id)){
			return runner1Id;
		}
		return null;
	}
	@Override
	public String toString() {
		return runner1Id + " : "+runner1Score+ " - "   +runner2Id + " : " +runner2Score;
	}

}
